package p.ithorns.framework.common.codec;

/**
 * CRC16MCodec
 * TODO
 *
 * @author ithorns
 * @version 1.0
 * @date 2020/2/23 22:01
 */
public class CRC16MCodec {
    /**
     * 一个字节包含位的数量 8
     */
    private static final int BITS_OF_BYTE = 8;
    /**
     * 多项式
     */
    private static final int POLYNOMIAL = 0xA001;
    /**
     * 初始值
     */
    private static final int CRC = 0xFFFF;

    /**
     * CRC16 大端序
     *
     * @param bytes 编码内容
     * @return 编码结果
     */
    public static int getBE(byte[] bytes) {
        int res = CRC;
        for (byte b : bytes) {
            res ^= ((int) b & 0x00FF);
            for (int j = 0; j < BITS_OF_BYTE; j++) {
                if ((res & 0x0001) != 0) {
                    res >>= 1;
                    res ^= POLYNOMIAL;
                } else {
                    res >>= 1;
                }
            }
        }
        //高低位转换
        return res ^= 0x0000;
    }

    /**
     * CRC16 小端序
     *
     * @param bytes -
     * @return int
     */
    public static int getLE(byte[] bytes) {
        return reverse(getBE(bytes));
    }

    /**
     * 生成CRC16M 的hex
     * 默认小端序
     *
     * @param bytes -
     * @return String
     */
    public static String toHexStr(byte[] bytes) {
        int i = reverse(getBE(bytes));
        return String.format("%04x", i).toUpperCase();
    }

    /**
     * 翻转16位的高八位和低八位字节
     *
     * @param src 翻转数字
     * @return 翻转结果
     */
    private static int reverse(int src) {
        return ((src & 0x0000FF00) >> 8) | ((src & 0x000000FF) << 8);
    }

    public static String revert(int x) {

        //将x转化为二进制
        String y = Integer.toBinaryString(x);

        StringBuffer sb = new StringBuffer();
        if (y.length() % 4 != 0) {
            //把0补齐
            for (int i = 0; i < 4 - y.length() % 4; i++) {
                sb.append("0");
            }
        }
        sb.append(y);
        //对二进制进行反转
        sb.reverse();
        //2进制转化为10进制
        long z = Long.valueOf(sb.toString(), 2);
        String result = Long.toHexString(z);

        return result;
    }


    /*
    *
    *
    *   uint16_t crc16_compute(uint8_t const * p_data, uint16_t size, uint16_t const * p_crc)
    {
        uint16_t crc;

        crc = (p_crc == NULL) ? 0xFFFF : ~(*p_crc);
        for (uint16_t i = 0; i < size; i++)
        {
            crc = crc ^ p_data[i];
            for (uint8_t j = 8; j > 0; j--)
            {
                crc = (crc >> 1) ^ (0x1021U & ((crc & 1) ? 0xFFFF : 0));
            }
        }
        return ~crc;
    }*/
}